// uni-app请求封装
/*
*router       String  请求接口
*data/param   Object  请求参数
*methods      String  请求方法
*bMsg         String  提示窗口请求前提示语
*eMsg		  String  提示窗口请求后提示语
*errorMsg     String  提示窗口错误提示语
*isBack		  Boolean 请求结束是否返回
*backTime	  Number  请求结束是否返回等待时间
*needToken    Boolean 是否需要token
*hideError    Boolean 是否显示错误报错
*/
import enviroment from "./enviroment";

interface File{
	path: string
	size?: number
	status?: 'start' | 'doing' | 'success' | 'fail' | 'noPermission'
	usr?: string
	response?: any
	url?: string
}

export default class Request{
	static socketRequest = null
	static socketCount = 0
	static socketStatus = false
	static socketing = false
	static socketTimer = null
	static monitorSocketTimer = null
	
	/**
	 * http请求
	 */
	http (request:{
		url?: string
		api: string
		methods: 'GET' | 'POST' | 'DELETE' | 'CONNECT' | 'HEAD' | 'OPTIONS' | 'PUT' | 'TRACE'
		data?: any
		param?: any
		showLoading?: boolean
		message?: string
		header?: Object
		resonpes?: any
	} = {
		api: "",
		methods: "GET",
		header: null,
		showLoading: false,
		message: ""
	}):Promise<any> {
		if(request.showLoading){
			uni.showLoading({title:request.message || '',mask:true})
		}
        if(!request.header)request.header = request.data ? enviroment.getGetHeader() : enviroment.getPostHeader();
        request.data = request.data || request.param || {}
        for(let key in request.data){
            if(request.data[key] === null || request.data[key] === undefined || request.data[key] === '')delete request.data[key]
        }

		// 返回promise
		return new Promise((resolve,reject) => {
			// 请求
			uni.request({
				url: `${enviroment.getUrl()}${request.api}`,
				data: request.data,
				header:request.header,
				method:request.methods,
				timeout:30000,
				success: (resonpes:any) => {
					if(request.showLoading)uni.hideLoading();
					console.log("************************我的请求参数***********************")
					request.resonpes = resonpes.data;
					request.url = `${enviroment.getUrl()}${request.api}`
					enviroment.getRequestResult(resolve, reject, resonpes)
					console.log(request)
				},
				fail:(error) =>{
					if(request.showLoading)uni.hideLoading();
					reject(error)
				}
			})
		})
	}
	
	/**
	 * post请求
	 */
	static post = (request:{
		api: string
		showLoading?: boolean
		messgae?: string
		header?: Object
		data?: Object
		resonpes?: Object
		url?: string
	} = {
		api: '',
		showLoading: false,
		messgae: '',
		header: undefined,
		data: {}
	}):Promise<any> =>{
		if(request.showLoading){
			uni.showLoading({title:request.messgae, mask:true})
		}
		request.header = request.header || enviroment.getPostHeader();
		for(let key in request.data){
		    if(request.data[key] === null || request.data[key] === undefined || request.data[key] === '')delete request.data[key]
		}
		return new Promise((resolve, reject) => {
			// 请求
			uni.request({
				url: `${enviroment.getUrl()}${request.api}`,
				data: request.data,
				header: request.header,
				method: 'POST',
				timeout: 30000,
				success: (resonpes:any) => {
					if(request.showLoading)uni.hideLoading();
					console.log("************************我的请求参数***********************")
					request.resonpes = resonpes.data;
					request.url = `${enviroment.getUrl()}${request.api}`;
					enviroment.getRequestResult(resolve, reject, resonpes)
					console.log(request)
				},
				fail:(error) =>{
					uni.hideLoading();
					reject(error)
				}
			})
		})
	}
	
	/**
	 * get请求
	 */
	static get = (request:{
		api: string
		showLoading?: boolean
		messgae?: string
		header?: Object
		params?: Object
		resonpes?: Object
		url?: string
	} = {
		api: '',
		showLoading: false,
		messgae: '',
		header: undefined,
		params: {}
	}):Promise<any> =>{
		if(request.showLoading){
			uni.showLoading({title:request.messgae, mask:true})
		}
		request.header = request.header || enviroment.getPostHeader();
		for(let key in request.params){
		    if(request.params[key] === null || request.params[key] === undefined || request.params[key] === '')delete request.params[key]
		}
		return new Promise((resolve, reject) => {
			// 请求
			uni.request({
				url: `${enviroment.getUrl()}${request.api}`,
				data: request.params,
				header: request.header,
				method: 'GET',
				timeout: 30000,
				success: (resonpes:any) => {
					if(request.showLoading)uni.hideLoading();
					console.log("************************我的请求参数***********************")
					request.resonpes = resonpes.data;
					request.url = `${enviroment.getUrl()}${request.api}`;
					enviroment.getRequestResult(resolve, reject, resonpes)
					console.log(request)
				},
				fail:(error) =>{
					uni.hideLoading();
					reject(error)
				}
			})
		})
	}
	
	/**
	 * 上传
	 */
	static upload(request : {
		url?: string
		fileList: File | File[]
		name?: string
		bMsg?: string
		successMsg?: string
		failMsg?: string
		response?: any
	}) : Promise<any> {
		if (!Array.isArray(request.fileList)) {
			request.fileList = [request.fileList];
		}
		var fileList:File[] = request.fileList;
		uni.showLoading({ title: request.bMsg || '', mask: true })
		var uploadEnd = true;  //是否上传成功状态
		var temporary = [];    //上传完成后临时存储数组

		return new Promise((resolve) => {
			if (fileList.length === 0) {
				resolve(temporary)
				uni.hideLoading()
			} else {
				var timer = setInterval(function () {
					if (uploadEnd && temporary.length <= fileList.length) {
						let file = fileList[temporary.length]
						if(file.status === 'success'){
							temporary.push(file);
						}else{
							uploadEnd = false;
							file.status = 'doing'
							uni.uploadFile({
								url: request.url || enviroment.getUploadUrl(),
								filePath: file.path,
								header: enviroment.getHeader(),
								name: request.name || 'file',
								success(response:any):void {
									response.data = JSON.parse(response.data)
									file.response = response.data;
									uploadEnd = true;
									file = enviroment.getUploadResult(response, file)
									temporary.push(file);
									if (file.status === 'noPermission' || temporary.length >= fileList.length) {
										clearInterval(timer);
										uni.hideLoading();
										resolve(temporary)
									}
								}, fail(err) {
									file.response = err
									uploadEnd = true
									file.status = 'fail'
									temporary.push(file);
									if (temporary.length >= fileList.length) {
										clearInterval(timer);
										uni.hideLoading();
										resolve(temporary)
									}
								}
							})
						}
					}
				}, 100)
			}
		})
	}
	
	/**
	 * 下载
	 */
	static download = ():void => {
		
	}
	
	/**
	 * 连接socket
	 * @param {string} api 请求api
	 * @param {Object} header 请求头
	 * @param {'GET' | 'OPTIONS' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'TRACE' | 'CONNECT'} method 请求方法
	 * @param {string[]} protocols 子协议数组
	 * @param {boolean} autoConnect 断开是否自动重连
	 * @param {number} autoConnectInterval 断开自动重连间隔
	 * @param {string | ArrayBuffer} pingData 心跳的数据
	 * @param {number} pingInterval 心跳时间间隔
	 * @param {number} limit 连接失败重连次数
	 * @param {number} connectInterval 连接失败重连间隔
	 * @param {Function} success 连接成功的回调
	 * @param {Function} fail 连接失败的回调
	 * @param {Function} complete 连接的回调
	 * @param {Function} open 打开socket的回调
	 * @param {Function} error 连接socket失败的回调
	 * @param {Function} on 消息推送的回调
	 * @param {Function} close 关闭socket的回调
	 * @param {Function} ping 发送消息成功的回调
	 */
	static connectSocket (request:{
		api: string
		header?: Object
		method?: 'GET' | 'OPTIONS' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'TRACE' | 'CONNECT'
		protocols?: string[]
		autoConnect?: boolean
		autoConnectInterval?: number
		pingData?: string | ArrayBuffer
		pingInterval?: number
		limit?: number
		connectInterval?: number
		success?: any
		fail?: any
		complete?: any
		open?: any
		error?: any
		on?: any
		close?: any
		ping?: any
	}){
		return new Promise((resolve: any, reject: any) => {
			if(Request.socketing)reject()
			request.pingInterval = request.pingInterval || 10000
			request.limit = request.limit || 100
			request.connectInterval = request.connectInterval || 1000
			request.autoConnectInterval = request.autoConnectInterval || 60000
			if(!request.success){
				request.success = (result:any):void => {
					console.log('socket连接成功', result)
				}
			}
			if(!request.fail){
				request.fail = (result:any):void => {
					console.log('socket连接失败', result)
				}
			}
			if(!request.ping){
				request.ping = (result:any):void => {
					// console.log('socket心跳', result)
				}
			}
			Request.socketRequest = request
			Request.socketing = true
			Request.socketCount += 1
			if(Request.socketStatus){
				resolve()
			}else{
				uni.onSocketOpen((result:any):void => {
					console.log('socket打开成功', result)
					Request.socketStatus = true
					Request.socketCount = 0
					Request.socketing = false
					if(request.open){
						request.open(result)
					}
					if(Request.socketTimer)clearInterval(Request.socketTimer)
					Request.socketTimer = setInterval(() => {
						Request.sendSocketMessage({
							data: request.pingData,
							success: request.ping
						})
						if(request.autoConnect)Request.monitorSocket()
					}, request.pingInterval)
					resolve()
				})
				
				uni.connectSocket({
					url: `${enviroment.getSocketUrl()}${request.api}`,
					header: request.header || enviroment.getPostHeader(),
					method: request.method || 'GET',
					protocols: request.protocols,
					success: request.success,
					fail: request.fail,
					complete: request.complete
				})
				
				uni.onSocketError((result:any):void => {
					console.log('socket连接失败', result)
					if(Request.socketTimer)clearInterval(Request.socketTimer)
					if(Request.socketCount < Request.socketRequest.limit){
						setTimeout(() => {
							Request.connectSocket(Request.socketRequest)
						}, request.connectInterval)
					}else{
						Request.socketStatus = false
						Request.socketCount = 0
						Request.socketing = false
						if(request.autoConnect)Request.monitorSocket()
					}
					request.error && request.error(result)
				})
				
				uni.onSocketMessage((result:any):void => {
					// console.log('socket消息通知', result)
					request.on && request.on(result)
				})
				
				uni.onSocketClose((result:any):void => {
					console.log('socket断开连接', result)
					if(Request.socketTimer)clearInterval(Request.socketTimer)
					Request.socketStatus = false
					Request.socketCount = 0
					Request.socketing = false
					request.close && request.close(result)
				});
			}
		})
	}
	
	/**
	 * 发送socket消息
	 * @param {string | ArrayBuffer} data 发送的数据
	 * @param {Function} success 发送成功的回调
	 * @param {Function} fail 发送失败的回调
	 * @param {Function} complete 请求的回调
	 */
	static sendSocketMessage (request: {
		data: string | ArrayBuffer
		success?: any
		fail?: any
		complete?: any
	}){
		if(!Request.socketStatus){
			if(Request.socketRequest && !Request.socketing){
				Request.connectSocket(Request.socketRequest).then(()=>{
					Request.sendSocketMessage(request)
				})
			}
		}else{
			// console.log('socket发送消息',request.data)
			uni.sendSocketMessage({
				data: request.data,
				success: request.success,
				fail: request.fail,
				complete: request.complete
			});
		}
	}
	
	/**
	 * 关闭socket
	 * @param {number} code 状态码
	 * @param {string} reason 关闭原因
	 * @param {Function} success 关闭成功的回调
	 * @param {Function} fail 关闭失败的回调
	 * @param {Function} complete 请求的回调
	 */
	static closeSocket (request:{
		code?: number
		reason?: string
		success?: any
		fail?: any
		complete?: any
	}){
		if(Request.socketStatus){
			uni.closeSocket({
				code: request.code || 1000,
				reason: request.reason || '主动关闭webSocket连接',
				success: request.success,
				fail: request.fail,
				complete: request.complete
			})
		}
	}
	
	/**
	 * 自动监听socket断开重连
	 */
	static monitorSocket ():void {
		if(Request.monitorSocketTimer)clearInterval(Request.monitorSocketTimer)
		Request.monitorSocketTimer = setTimeout(()=>{
			Request.connectSocket(Request.socketRequest)
		},Request.socketRequest.autoConnectInterval)
	}
}
